#include "LogicDelete.h"

string LogicDelete::execute(Parser::PARSED_COMMAND parsedCommand, 
								vector<Task>& tasksVector,
								Data* _data,
								Writer* _writer) {

	string status;

	if( parsedCommand.commandType == Parser::DELETE_TASKID ) {
		status = deleteTaskByIndex(parsedCommand, tasksVector, _data, _writer);
	} else if( parsedCommand.commandType == Parser::DELETE_DONE ) {
		status = deleteDoneTask(parsedCommand, tasksVector, _data, _writer);
	} else if( parsedCommand.commandType == Parser::DELETE_SEARCHTERM ) {
		status = deleteTaskByString(parsedCommand, tasksVector, _data, _writer);
	}

	return status;
}

string LogicDelete::deleteTaskByString(Parser::PARSED_COMMAND parsedCommand, vector<Task>& tasksVector, Data* _data, Writer* _writer) {

	string statusMessage;
	string term;
	bool typeName;
	bool typeSearchTerm;

	term = parsedCommand.deleteSearchTerm;

	typeName = isDeleteByName(term, _data);
	typeSearchTerm = isDeleteBySearchTerm(term, _data);

	if( typeName ) {
		statusMessage = deleteTaskByName(parsedCommand, tasksVector, _data, _writer);
	} else if( typeSearchTerm ) {
		statusMessage = deleteTaskBySearchTerm(parsedCommand, tasksVector, _data, _writer);
	}

	return statusMessage;
}

string LogicDelete::deleteTaskByIndex(Parser::PARSED_COMMAND parsedCommand, vector<Task>& tasksVector, Data* _data, Writer* _writer) {
	
	string statusMessage;
	Data::DataFeedback dataFeedback;
	vector<Task> tasks;
	bool outOfBounds;
	stringstream display;
	
	int index = parsedCommand.deleteTaskID;

	outOfBounds = isOutOfBounds(index, tasksVector.size());
	
	if( outOfBounds ) {
		throw(INDEX_OUT_OF_BOUNDS_ERROR_MESSAGE);
	}

	int taskId = tasksVector[index-1].getTaskID();

	display << tasksVector[index-1].getTaskName();

	dataFeedback = _data->executeDeleteTaskID(taskId);

	if( dataFeedback == Data::SUCCESS ) {
		tasksVector.erase(tasksVector.begin()+index-1);
		tasks.clear();
		_data->getAll(tasks);
		_writer->write(tasks);
		statusMessage = DELETE_SUCCESS_MESSAGE + display.str();
	} else {
		statusMessage = DELETE_ERROR_MESSAGE;
		//logErrors(statusMessage, _undoState);
	}

	return statusMessage;
}

string LogicDelete::deleteTaskByName(Parser::PARSED_COMMAND parsedCommand, vector<Task>& tasksVector, Data* _data, Writer* _writer) {

	string statusMessage;
	string taskName;
	int taskId;
	Data::DataFeedback dataFeedback;
	vector<Task> tasks;
	vector<Task> displayTasks;
	bool multipleMatch;
	bool executed;
	stringstream display;

	taskName = parsedCommand.deleteSearchTerm;

	// insert try catch block here
	dataFeedback = _data->getByName(tasks ,taskName);
	
	tasksVector.clear();;

	if( tasks.empty() ) {
		throw(NOT_FOUND_ERROR_MESSAGE);
	}

	multipleMatch = isMultipleMatches(tasks.size());

	if( multipleMatch ) {
		copyTasks(tasks, tasksVector);
		executed = false;
	} else {
		taskId = tasks[FIRST_POSITION].getTaskID();
		tasksVector.push_back(tasks[FIRST_POSITION]);
		display << tasks[FIRST_POSITION].getTaskName();
		dataFeedback = _data->executeDeleteTaskID(taskId);
		executed = true;
	}

	if( executed == true && dataFeedback == Data::SUCCESS ) {
		tasks.clear();
		_data->getAll(tasks);
		_writer->write(tasks);
		statusMessage = DELETE_SUCCESS_MESSAGE + display.str();
	} else {
		statusMessage = DELETE_ERROR_MESSAGE;
		//logErrors(statusMessage, _undoState);
	}

	return statusMessage;
}

string LogicDelete::deleteTaskBySearchTerm(Parser::PARSED_COMMAND parsedCommand, vector<Task>& tasksVector, Data* _data, Writer* _writer) {
	
	string statusMessage;
	string searchTerm;
	int taskId;
	Data::DataFeedback dataFeedback;
	vector<Task> tasks;
	bool multipleMatch;
	bool executed;
	stringstream display;

	searchTerm = parsedCommand.deleteSearchTerm;

	dataFeedback = _data->getBySearchTerm(tasks, searchTerm);

	tasksVector.clear();

	if( tasks.empty() ) {
		throw(NOT_FOUND_ERROR_MESSAGE);
	}

	multipleMatch = isMultipleMatches(tasks.size());

	if( multipleMatch ) {
		copyTasks(tasks, tasksVector);
		executed = false;
	} else {
		taskId = tasks[FIRST_POSITION].getTaskID();
		tasksVector.push_back(tasks[FIRST_POSITION]);
		display << tasks[FIRST_POSITION].getTaskName();
		dataFeedback = _data->executeDeleteTaskID(taskId);
		executed = true;
	}

	if( executed == true && dataFeedback == Data::SUCCESS ) {
		tasks.clear();
		_data->getAll(tasks);
		_writer->write(tasks);
		statusMessage = DELETE_SUCCESS_MESSAGE + display.str();
	} else {
		statusMessage = DELETE_ERROR_MESSAGE;
		//logErrors(statusMessage, _undoState);
	}

	return statusMessage;
}

string LogicDelete::deleteDoneTask(Parser::PARSED_COMMAND parsedCommand, vector<Task>& tasksVector, Data* _data, Writer* _writer) {

	string statusMessage;
	int taskId;
	Data::DataFeedback dataFeedback;

	vector<Task> tasks;

	dataFeedback = _data->getByDone(tasks);
	
	if( dataFeedback == Data::NOT_FOUND ) {
		throw(NOT_FOUND_ERROR_MESSAGE);
	}

	tasksVector.clear();
	copyTasks(tasks, tasksVector);

	for( unsigned int i=0; i<tasks.size(); i++ ) {
		taskId = tasks[i].getTaskID();
		dataFeedback = _data->executeDeleteTaskID(taskId);
	}

	if(dataFeedback == Data::SUCCESS ) {
		tasks.clear();
		_data->getAll(tasks);
		_writer->write(tasks);
		statusMessage = DELETE_DONE_SUCCESS_MESSAGE;
	} else {
		statusMessage = DELETE_ERROR_MESSAGE;
		//logErrors(statusMessage, _undoState);
	}

	return statusMessage;
}

// this function determines whether it deletes by done
// returns TRUE if term matches keyword done
// returns FALSE otherwise
bool LogicDelete::isDeleteByDone(string term) {
	
	bool isDeleteTypeDone;
	if( term == DELETE_TYPE_DONE ) {
		isDeleteTypeDone = true;
	} else {
		isDeleteTypeDone = false;
	}

	return isDeleteTypeDone;
}

bool LogicDelete::isDeleteByName(string term, Data* _data) {

	bool isDeleteTypeName;

	vector<Task> tasks;
	_data->getByName(tasks, term);

	if( tasks.empty() ) {
		isDeleteTypeName = false;
	} else {
		isDeleteTypeName = true;
	}

	return isDeleteTypeName;
}

bool LogicDelete::isDeleteBySearchTerm(string term, Data* _data) {

	bool isDeleteSearchTerm;

	vector<Task> tasks;
	_data->getBySearchTerm(tasks, term);

	if( tasks.empty() ) {
		isDeleteSearchTerm = false;
	} else {
		isDeleteSearchTerm = true;
	}

	return isDeleteSearchTerm;
}

const string LogicDelete::DELETE_SUCCESS_MESSAGE = "Task Deleted: ";

const string LogicDelete::DELETE_DONE_SUCCESS_MESSAGE = "Done Tasks Deleted";

const string LogicDelete::DELETE_ERROR_MESSAGE = "Unable To Delete";

const string LogicDelete::DELETE_TYPE_DONE = "done";

const int LogicDelete::FIRST_POSITION = 0;